/**************************************************************************\
    Copyright Microsoft Corporation. All Rights Reserved.
\**************************************************************************/

// This file contains general utilities to aid in development.
// It is distinct from unit test Assert classes.
// Classes here generally shouldn't be exposed publicly since
// they're not particular to any library functionality.
// Because the classes here are internal, it's likely this file
// might be included in multiple assemblies.
namespace C4F.DevKit.Contacts.Standard
{
    using System;
    using System.Diagnostics;
    using System.Threading;

    internal static class Assert
    {
        [Conditional("DEBUG")]
        public static void Evaluate<T>(T argument)
        {
        }

        [Obsolete("Use Assert.AreEqual instead of Assert.Equals", false)]
        public static void Equals<T>(T expected, T actual)
        {
            AreEqual(expected, actual);
        }

        [Conditional("DEBUG")]
        public static void AreEqual<T>(T first, T second)
        {
            if (null == first)
            {
                // Two nulls are considered equal, regardless of type semantics.
                if (null != second && !second.Equals(first))
                {
                    Debugger.Break();
                }
            }
            else if (!first.Equals(second))
            {
                Debugger.Break();
            }
        }

        [Conditional("DEBUG")]
        public static void AreNotEqual<T>(T first, T second)
        {
            if (null == first)
            {
                // Two nulls are considered equal, regardless of type semantics.
                if (null == second || second.Equals(first))
                {
                    Debugger.Break();
                }
            }
            else if (first.Equals(second))
            {
                Debugger.Break();
            }
        }

        [Conditional("DEBUG")]
        public static void IsNotNull<T>(T first) where T : class
        {
            if (null == first)
            {
                Debugger.Break();
            }
        }

        [Conditional("DEBUG")]
        public static void Implies(bool condition, bool result)
        {
            if (condition && !result)
            {
                Debugger.Break();
            }
        }

        [Conditional("DEBUG")]
        public static void IsFalse(bool condition)
        {
            if (condition)
            {
                Debugger.Break();
            }
        }

        // Note: This displays the dialog modally before breaking into the debugger.
        [Conditional("DEBUG")]
        public static void IsFalse(bool condition, string message)
        {
            if (condition)
            {
                Debug.WriteLine("!IsFalse: " + message);
                Debugger.Break();
            }
        }

        [Conditional("DEBUG")]
        public static void IsTrue(bool condition)
        {
            if (!condition)
            {
                Debugger.Break();
            }
        }

        // Note: This displays the dialog modally before breaking into the debugger.
        [Conditional("DEBUG")]
        public static void IsTrue(bool condition, string message)
        {
            if (!condition)
            {
                Debug.WriteLine("!IsTrue: " + message);
                Debugger.Break();
            }
        }

        [Conditional("DEBUG")]
        public static void Fail()
        {
            Debugger.Break();
        }

        [Conditional("DEBUG")]
        public static void Fail(string message)
        {
            Debug.WriteLine("!Fail: " + message);
            Debugger.Break();
        }

        [Conditional("DEBUG")]
        public static void IsNull<T>(T item) where T : class
        {
            if (null != item)
            {
                Debugger.Break();
            }
        }

        [Conditional("DEBUG")]
        public static void BoundedInteger(int lowerBoundInclusive, int value, int upperBoundExclusive)
        {
            if (value < lowerBoundInclusive || value >= upperBoundExclusive)
            {
                Debugger.Break();
            }
        }

        /// <summary>
        /// Ensure that the current thread's apartment state is what's expected.
        /// </summary>
        /// <param name="requiredState">
        /// The required apartment state for the current thread.
        /// </param>
        /// <remarks>
        /// Breaks into the debugger if the assertion is false.
        /// </remarks>
        [Conditional("DEBUG")]
        public static void IsApartmentState(ApartmentState requiredState)
        {
            if (Thread.CurrentThread.GetApartmentState() != requiredState)
            {
                Debugger.Break();
            }
        }
    }
}
